package cn.itsource.ymcc.filter;

import cn.itsource.ymcc.result.JsonResult;
import cn.itsource.ymcc.util.UserContext;
import cn.itsource.ymcc.util.jwt.JwtUtils;
import cn.itsource.ymcc.util.jwt.Payload;
import cn.itsource.ymcc.util.jwt.PayloadData;
import cn.itsource.ymcc.util.jwt.RsaUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.security.PublicKey;
import java.util.List;

/**
 * 获取请求头，解析token，判断非空，刷新过期时间；如果是空返回一个“未登录”
 */
@Slf4j
@Component
public class AuthenticationFilter implements GlobalFilter, Ordered {
    @Autowired
    private ExcludeProperties excludeProperties;   //要放行的接口地址集合

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.先获取请求对象、响应对象  gateway是基于webflux封装的，它的请求、响应对象与HttpServletRequest不一样了
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        //2.放行我们在yml中配置的接口地址
        RequestPath path = request.getPath();
        log.info("本次请求地址：{}", path.value());



        //login/**
        if (excludeProperties.isExcluded(path.value())){//判断当前url是否被排除  有些路径不需要拦截
            return chain.filter(exchange); //放行
        }



        //path请求路径  /order/getxx  = token 那个用户

        // /order/getxx + token  = key 存入redis  过期时间最多2秒
        // 幂等性 一般针对 添加 和  修改


        //下面都是需要拦截的
        //3.获取请求头
        List<String> headers = request.getHeaders().get(UserContext.JWT_TOKEN_NAME);

        try {
            //4.判断
            if(headers != null && headers.size() > 0){
                String token = headers.get(0);
                //5.利用JWT工具类解析token   私钥加密 公钥解密

                JSONObject user = UserContext.getUser(token);
                if(user != null){

                    //表示已登录  直接放行
                    return chain.filter(exchange);
                }
//                if(user != null){
//                    PayloadData payloadData = user.getUserInfo();
//                    if(payloadData != null){
//                        Object login = payloadData.getLogin();
//                        if(login != null){
//                            //表示已登录  直接放行
//                            return chain.filter(exchange);
//                        }
//                    }
//                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //6.回“noLogin”
        response.getHeaders().set("content-type","application/json;charset=UTF-8");
        JsonResult jsonResult = JsonResult.error("noLogin");
        byte[] bytes = JSON.toJSONBytes(jsonResult);//阿里巴巴的json
        DataBuffer wrapper = response.bufferFactory().wrap(bytes);
        return response.writeWith(Mono.just(wrapper));
    }

    @Override
    public int getOrder() {
        return 0;
    }
}